package com.wgz.medicalmanagement.service.impl;

import com.wgz.medicalmanagement.common.config.AIConfig;
import com.wgz.medicalmanagement.common.config.AIProperties;
import com.wgz.medicalmanagement.domain.dto.ai.ChatCompletionRequest;
import com.wgz.medicalmanagement.domain.dto.ai.ChatCompletionResponse;
import com.wgz.medicalmanagement.domain.dto.ai.ChatMessage;
import com.wgz.medicalmanagement.service.AIDiagnosisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * AI诊断服务实现类
 * 处理与AI诊断相关的业务逻辑
 *
 * @author medical
 */
@Slf4j
@Service
public class AIDiagnosisServiceImpl implements AIDiagnosisService {

    private final AIProperties aiProperties;
    private final RestTemplate aiRestTemplate;

    // 按用户ID区分的对话历史，使用ConcurrentHashMap保证线程安全
    private final Map<Long, List<ChatMessage>> userConversationHistory = new ConcurrentHashMap<>();
    
    // 系统提示，指导AI的行为
    private static final String SYSTEM_PROMPT = 
            "你是一个经验丰富的可爱的医疗助手，可以帮助医生进行智能诊断。" +
            "你应该根据患者的症状提供可能的诊断建议、需要进一步了解的信息，以及可能需要的检查。" +
            "给出的建议要专业、准确、有帮助，但需要明确你不是替代医生的专业判断，只是提供参考信息。" +
            "回答应当简洁、有条理，使用医学专业术语的同时也要确保医生容易理解。" +
            "如果症状表明可能有紧急情况，请特别强调这一点，并建议及时就医。" +
            "对于专业医疗知识的回答，请使用temperature=0.5；对于一般医学咨询，请使用temperature=1.0。" +
            "请用中文回答，并尽可能多地提供有价值的信息。";

    /**
     * 初始化对话
     * 添加系统提示到对话历史
     */
    public AIDiagnosisServiceImpl(AIProperties aiProperties, RestTemplate aiRestTemplate) {
        this.aiProperties = aiProperties;
        this.aiRestTemplate = aiRestTemplate;
    }

    /**
     * 获取指定用户的对话历史，如果不存在则初始化
     * @param userId 用户ID
     * @return 用户的对话历史列表
     */
    private List<ChatMessage> getUserConversationHistory(Long userId) {
        return userConversationHistory.computeIfAbsent(userId, k -> {
            List<ChatMessage> newHistory = new ArrayList<>();
            // 初始化新的对话历史，添加系统提示
            newHistory.add(ChatMessage.systemMessage(SYSTEM_PROMPT));
            return newHistory;
        });
    }

    @Override
    public String chatWithAI(String message) {
        throw new IllegalArgumentException("必须提供有效的用户ID，无法使用默认用户");
    }

    /**
     * 发送消息到AI并获取回复，包含用户ID参数
     *
     * @param userId 用户ID
     * @param message 用户输入的消息
     * @return AI的回复
     */
    public String chatWithAI(Long userId, String message) {
        log.info("用户{}发送消息到AI诊断服务: {}", userId, message);
        
        try {
            // 获取用户的对话历史
            List<ChatMessage> conversationHistory = getUserConversationHistory(userId);
            
            // 添加用户消息到对话历史
            conversationHistory.add(ChatMessage.userMessage(message));
            
            // 限制对话历史长度，防止超出Token限制
            if (conversationHistory.size() > 10) {
                // 保留系统提示和最近的对话
                List<ChatMessage> trimmedHistory = new ArrayList<>();
                trimmedHistory.add(conversationHistory.get(0)); // 系统提示
                trimmedHistory.addAll(conversationHistory.subList(
                        conversationHistory.size() - 9, conversationHistory.size()));
                conversationHistory.clear();
                conversationHistory.addAll(trimmedHistory);
            }
            
            // 根据消息内容调整temperature
            Double temperature = aiProperties.getTemperature();
            // 如果消息包含医学专业术语或特定的诊断查询，使用较低的temperature
            if (containsMedicalTerms(message)) {
                temperature = 0.5; // 更确定性的回答
            } else if (message.contains("创意") || message.contains("建议") || message.contains("如何")) {
                temperature = 1.3; // 更有创意的回答
            }
            
            log.info("使用temperature值: {}", temperature);
            
            // 打印配置信息，帮助调试
            log.debug("API URL: {}", aiProperties.getUrl());
            log.debug("API模型: {}", aiProperties.getModel());
            
            // 创建请求
            ChatCompletionRequest request = ChatCompletionRequest.builder()
                    .model(aiProperties.getModel())
                    .messages(new ArrayList<>(conversationHistory))
                    .temperature(temperature)
                    .max_tokens(aiProperties.getMaxTokens())
                    .build();
            
            // 打印请求内容，帮助调试
            log.info("发送AI请求，消息数量: {}", request.getMessages().size());
            
            // 创建HTTP头
            HttpHeaders headers = AIConfig.createHeaders(aiProperties.getKey());
            
            // 创建HTTP实体
            HttpEntity<ChatCompletionRequest> httpEntity = new HttpEntity<>(request, headers);
            
            // 发送请求
            log.info("正在调用DeepSeek API...");
            ResponseEntity<ChatCompletionResponse> response = 
                    aiRestTemplate.postForEntity(aiProperties.getUrl(), httpEntity, ChatCompletionResponse.class);
            
            if (response.getBody() != null && response.getBody().getChoices() != null && !response.getBody().getChoices().isEmpty()) {
                ChatMessage aiMessage = response.getBody().getChoices().get(0).getMessage();
                
                // 添加AI回复到对话历史
                conversationHistory.add(aiMessage);
                
                log.info("DeepSeek模型成功生成回复，长度: {}", aiMessage.getContent().length());
                // 记录token使用情况（如果存在）
                if (response.getBody().getUsage() != null) {
                    log.info("Token使用情况 - 输入: {}, 输出: {}, 总计: {}", 
                            response.getBody().getUsage().getPromptTokens(),
                            response.getBody().getUsage().getCompletionTokens(),
                            response.getBody().getUsage().getTotalTokens());
                }
                
                return aiMessage.getContent();
            } else {
                log.error("AI回复为空或无效");
                return "抱歉，AI服务目前无法生成回复。请稍后再试。";
            }
            
        } catch (Exception e) {
            log.error("处理AI诊断请求时出错", e);
            log.error("错误类型: {}", e.getClass().getName());
            log.error("错误消息: {}", e.getMessage());
            
            // 记录堆栈跟踪
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw));
            log.error("堆栈跟踪: {}", sw.toString());
            
            // 直接返回错误信息，不再使用本地模拟响应
            String errorMessage = "AI服务暂时无法响应: " + e.getMessage() + 
                "。请尝试检查API密钥、网络连接或稍后再试。";
            
            // 添加错误信息到对话历史，但标记为错误
            List<ChatMessage> conversationHistory = getUserConversationHistory(userId);
            conversationHistory.add(ChatMessage.systemMessage("[错误] " + errorMessage));
            
            return errorMessage;
        }
    }

    @Override
    public String exportDiagnosisReport(Long patientId) {
        log.info("导出患者 {} 的诊断报告", patientId);
        
        try {
            // 获取患者的对话历史，用于生成报告
            List<ChatMessage> conversationHistory = getUserConversationHistory(patientId);
            
            // 创建报告生成提示
            List<ChatMessage> reportMessages = new ArrayList<>();
            reportMessages.add(ChatMessage.systemMessage("你是一个医疗报告生成专家。请根据提供的患者信息和诊断对话，" +
                    "生成一份专业、结构化的医疗诊断报告。报告应包含：患者基本信息、主诉、现病史、诊断意见、治疗建议等部分。" +
                    "格式应专业规范，适合打印成PDF文档。"));
            
            // 添加对话历史中的最后几条消息，作为报告生成的参考
            if (conversationHistory.size() > 1) {
                // 跳过系统消息，只提取有价值的对话
                for (int i = 1; i < Math.min(conversationHistory.size(), 7); i++) {
                    reportMessages.add(conversationHistory.get(i));
                }
            }
            
            // 添加生成报告的指令
            reportMessages.add(ChatMessage.userMessage("请根据以上对话内容，为患者ID为" + patientId + "生成一份正式的诊断报告。" + 
                    "设定该患者为45岁男性，职业为办公室职员，既往有高血压病史。请确保报告格式专业，内容全面。"));

            // 这里继续原有的报告生成逻辑...
            
            // 实现中可能需要调用AI服务生成报告
            // 为简化示例，这里返回一个模拟URL
            return "/reports/patient_" + patientId + "_report_" + System.currentTimeMillis() + ".pdf";
        } catch (Exception e) {
            log.error("生成诊断报告时出错", e);
            throw e;
        }
    }
    
    /**
     * 检测消息是否包含医学专业术语
     * @param message 用户消息
     * @return 是否包含医学术语
     */
    private boolean containsMedicalTerms(String message) {
        // 常见医学术语关键词
        String[] medicalKeywords = {
            "诊断", "症状", "疾病", "治疗", "用药", "副作用", "剂量",
            "检查", "手术", "化验", "结果", "病理", "病因", "预后",
            "慢性", "急性", "炎症", "感染", "过敏", "免疫", "血压"
        };
        
        String lowerMessage = message.toLowerCase();
        for (String keyword : medicalKeywords) {
            if (lowerMessage.contains(keyword)) {
                return true;
            }
        }
        
        return false;
    }
} 